package com.csaba.swing.gui.login;

import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;

import com.csaba.util.encryption.EncryptedStore;

@SuppressWarnings( "serial" )
public class LoginDetails extends HashMap<String, String>
{
	private static final String LD_TIMESTAMP = "timestamp"; //$NON-NLS-1$
	private final static String CUSTOMER_PROP_ID = LoginDetails.class.getName();
	private final static String PROP_SEPARATOR = "/"; //$NON-NLS-1$

	private final String bankCode;
	private final String loginId;

	public LoginDetails( final String bankCode, final String loginId )
	{
		super();
		this.bankCode = bankCode;
		this.loginId = loginId;
	}

	@Override
	public String toString()
	{
		return getBankCode() + " - " + getLoginId(); //$NON-NLS-1$
	}

	public static void store( final LoginDetails details )
	{
		//create prefix
		final String prefix = CUSTOMER_PROP_ID + PROP_SEPARATOR + details.bankCode + PROP_SEPARATOR + details.loginId
				+ PROP_SEPARATOR;

		// put timestamp on the details before saving it. 
		// it is necessary as in some cases there is no property to 
		// save (but only the login ID and bank name that is not a 
		// real property)
		details.put(LD_TIMESTAMP, Calendar.getInstance().toString());

		//put all details to Encryption store
		final EncryptedStore store = EncryptedStore.getInstance();
		for ( final String key : details.keySet() )
		{
			final String name = prefix + key;
			final String value = details.get(key);
			store.putValue(name, value);
		}
	}

	public static LoginDetails[] loadAll()
	{
		final EncryptedStore store = EncryptedStore.getInstance();
		if ( !store.isOpen() )
		{
			return new LoginDetails[0];
		}

		final String[] properties = store.getKeysStartWith(CUSTOMER_PROP_ID);

		//collect prefixes
		final Set<String> prefixes = new HashSet<String>();
		for ( final String string : properties )
		{
			//cut last element in the key
			final String prefix = string.substring(0, string.lastIndexOf(PROP_SEPARATOR) + 1);
			prefixes.add(prefix);
		}

		//load details
		final LoginDetails[] all = new LoginDetails[prefixes.size()];
		int i = 0;
		for ( final String prefix : prefixes )
		{
			all[i++] = load(prefix);
		}
		return all;
	}

	public static LoginDetails load( final String prefix )
	{
		//get bank code and customer id out of prefix
		final StringTokenizer prefixParts = new StringTokenizer(prefix, PROP_SEPARATOR);
		if ( prefixParts.countTokens() != 3 )
			throw new IllegalArgumentException("Invalid prefix:" + prefix);
		if ( !prefixParts.nextToken().equals(CUSTOMER_PROP_ID) )
			throw new IllegalArgumentException("Invalid prefix ID:" + prefix);

		final String bankCode = prefixParts.nextToken();
		final String loginId = prefixParts.nextToken();

		//get all details from Encryption store
		final LoginDetails result = new LoginDetails(bankCode, loginId);

		final EncryptedStore store = EncryptedStore.getInstance();
		if ( !store.isOpen() )
		{
			throw new IllegalStateException(
					"Cannot load login details as EncryptedStore is closed or not yet initialized.");
		}

		final String[] properties = store.getKeysStartWith(prefix);
		for ( final String key : properties )
		{
			final Object value = store.getValue(key);
			final String name = key.substring(prefix.length());
			result.put(name, (String) value);
		}

		return result;
	}

	public String getLoginId()
	{
		return loginId;
	}

	public String getBankCode()
	{
		return bankCode;
	}
}
